package com.boxman

import android.annotation.SuppressLint
import android.content.res.AssetManager
import android.graphics.BitmapFactory
import android.os.Handler
import android.os.Handler.Callback
import android.os.Looper
import android.os.Message

import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.IntSize

import java.io.InputStream
import java.util.Timer
import java.util.TimerTask

// 小人
class Man: Box, Callback {
    // 定时器任务类
    /**
     * 构造方法。
     * @param callback  回调
     */
    private class GameTimerTask(callback: Callback?): TimerTask() {
        private val mCallback = Handler(Looper.getMainLooper(), callback)   // 回调

        /**
         * 定时器事件的响应方法。
         */
        override fun run() {
            mCallback.sendEmptyMessage(Const.UM_TIMER)
        }
    }

    private var mCurrentImage1: ImageBitmap                     // 当前图片1
    private var mCurrentImage2: ImageBitmap                     // 当前图片2
    private lateinit var mDanceImage: MutableState<ImageBitmap> // 跳舞图片
    private lateinit var mImageLeft1: ImageBitmap               // 左图片1
    private lateinit var mImageLeft2: ImageBitmap               // 左图片2
    private lateinit var mImageRight1: ImageBitmap              // 右图片1
    private lateinit var mImageRight2: ImageBitmap              // 右图片2
    private lateinit var mImageUp1: ImageBitmap                 // 上图片1
    private lateinit var mImageUp2: ImageBitmap                 // 上图片2
    private var mTimerTask: TimerTask                           // 定时器任务

    /**
     * 构造方法。
     * @param assetManager  资产管理者
     * @param back          背后对象
     * @param type          类型
     * @param x, y          左上角坐标
     */
    @SuppressLint("DefaultLocale")
    constructor(assetManager: AssetManager, back: BaseGameObject, type: Type, x: Int, y: Int):
        super(assetManager, back, type, x, y) {
        // 初始化成员
        mCurrentImage1 = mImage
        mCurrentImage2 = mImage2

        // 加载所有图片
        var imageFilePath: String
        var inputStream: InputStream
        try {
            imageFilePath = String.format(Const.IMAGE_FILE_PATH, type.ordinal * 10 + 2)
            inputStream = assetManager.open(imageFilePath)
            mImageLeft1 = BitmapFactory.decodeStream(inputStream).asImageBitmap()

            imageFilePath = String.format(Const.IMAGE_FILE_PATH, type.ordinal * 10 + 3)
            inputStream = assetManager.open(imageFilePath)
            mImageLeft2 = BitmapFactory.decodeStream(inputStream).asImageBitmap()

            imageFilePath = String.format(Const.IMAGE_FILE_PATH, type.ordinal * 10 + 4)
            inputStream = assetManager.open(imageFilePath)
            mImageRight1 = BitmapFactory.decodeStream(inputStream).asImageBitmap()

            imageFilePath = String.format(Const.IMAGE_FILE_PATH, type.ordinal * 10 + 5)
            inputStream = assetManager.open(imageFilePath)
            mImageRight2 = BitmapFactory.decodeStream(inputStream).asImageBitmap()

            imageFilePath = String.format(Const.IMAGE_FILE_PATH, type.ordinal * 10 + 6)
            inputStream = assetManager.open(imageFilePath)
            mImageUp1 = BitmapFactory.decodeStream(inputStream).asImageBitmap()

            imageFilePath = String.format(Const.IMAGE_FILE_PATH, type.ordinal * 10 + 7)
            inputStream = assetManager.open(imageFilePath)
            mImageUp2 = BitmapFactory.decodeStream(inputStream).asImageBitmap()
        } catch (e: Exception) {
            e.printStackTrace()
        }

        // 开始跳舞
        mTimerTask = GameTimerTask(this)
        Timer().schedule(mTimerTask, Const.TIMER_INIT, Const.TIMER_INIT)
    }

    /**
     * 绘制自身。
     * @param drawer    绘图者
     */
    override fun draw(drawer: DrawScope) {
        drawer.drawImage(
            image = mDanceImage.value,
            srcSize = IntSize(mDanceImage.value.width, mDanceImage.value.height),
            dstOffset = IntOffset(mX * sSize, mY * sSize),
            dstSize = IntSize(sSize, sSize)
        )
    }

    /**
     * 自定义事件的响应方法。
     * @param message   事件相关信息
     */
    override fun handleMessage(message: Message): Boolean {
        mDanceImage.value = if (mDanceImage.value == mCurrentImage1) mCurrentImage2 else mCurrentImage1
        return true
    }

    /**
     * 初始化。
     */
    @Composable
    fun Init() {
        mDanceImage = remember {
            mutableStateOf(mCurrentImage1)
        }
    }

    /**
     * 移动。
     * @param direction     方向
     * @param moveResult    移动结果
     * @return 被推动的箱子
     */
    override fun move(direction: Int, moveResult: MoveResult): BaseGameObject? {
        var destX: Int = mX
        var destY: Int = mY   // 新位置的坐标

        // 根据方向，计算新位置的坐标和图片
        when (direction) {
            Const.DIRECTION_LEFT -> {
                destX--
                mCurrentImage1 = mImageLeft1
                mCurrentImage2 = mImageLeft2
            }
            Const.DIRECTION_RIGHT -> {
                destX++
                mCurrentImage1 = mImageRight1
                mCurrentImage2 = mImageRight2
            }
            Const.DIRECTION_UP -> {
                destY--
                mCurrentImage1 = mImageUp1
                mCurrentImage2 = mImageUp2
            }
            Const.DIRECTION_DOWN -> {
                destY++
                mCurrentImage1 = mImage
                mCurrentImage2 = mImage2
            }
        }

        // 重新设置图片
        mDanceImage.value = mCurrentImage1

        // 先移动旁边的物体
        val box: BaseGameObject? = Game.sBaseGameObjects[destY][destX]?.move(direction, moveResult)
        if (moveResult.result == MoveResult.Result.NO_MOVE) {
            return null
        }

        // 移动小人
        super.move(direction, moveResult)

        return box
    }

    /**
     * 停止跳舞。
     */
    fun stopDancing() {
        mTimerTask.cancel()
    }
}
